Wolfram Language on iOS

Rob Raguet-Schofield

Wolfram Research

Wolfram Language on iOS

Computation on device

CDFKit is an iOS library

Requires a custom app and Objective-C or Swift code

Interactive, beautiful, and relatively fast

Computation in cloud

WolframAlpha

WolframCloud documents

WolframCloud API

Typesetting

d+(a^(b^c))+(a^b)+(a^(2^2))

((a+b)/2)

(Sqrt[2])

a+(Sqrt[((a+b)/(c+d))])

Style[a+(1/x)+(1/(x^2))+(x^(2/3)),Red]

Framed["abc",FrameStyle->Blue,RoundingRadius->8]
Framed[TraditionalForm[x+y],FrameStyle->Red]

Style[a+Grid[{{b,x,x,x,x,x,x},{x,Item[x,Frame->True, Background->None],x,x,x,x,x},{x,x,x,x,x,x,x},{x,x,x,x,x,x,x}},Dividers->{False,2->True},Frame->{1->True,False},FrameStyle->{Dashing[2],Thickness[2],Blue},Background->Yellow,ItemSize->{2,2}],ItemBoxOptions->{Background->None},Background->Green]

Grid[Partition[Range[8^2],8],Frame->{None,None,Table[{k,k}->True,{k,10}]}]

CharacterRange["α","ω"]

Rotate[a(Sqrt[b]),Pi/4]

Graphics

Plot[Evaluate[Table[BesselJ[n,x],{n,4}]],{x,0,10},Filling->Axis]

GraphPlot[Table[i->Mod[i^2,102],{i,0,102}]]

Graphics[{{Red,Disk[{5,5},4]},Raster[Table[{x,y,x,y}, {x,.1,1,.1},{y,.1,1,.1}]]}]

Graphics3D

RegionPlot3D[x y z<1,{x,-5,5},{y,-5,5},{z,-5,5},PlotStyle->Directive[Yellow,Opacity[0.5]],Mesh->None]

Dynamic

Checkbox[Dynamic[x]]

Graphics[{Red,Disk[{0,.25},.5],Green,Disk[{-.33,-.25},.5],Blue,Disk[{.33,-.25},.5]},Background->Dynamic[If[x,RGBColor[0,0,0],RGBColor[1,1,1]]]]

Manipulate

Manipulate[Expand[(a+b)^n],{n,1,100,1}]

Manipulate[ContourPlot3D[x^2+y^2+a z^3==1,{x,-2,2},{y,-2,2},{z,-2,2},Mesh->None],{a,-2,2}]

CDFKit

CDFKit is an iOS SDK.  Clients can embed CDFKit into their iOS applications to

Display and interact with CDF content

Perform evaluations of Wolfram Language expressions

Apps can revolve around CDF content (rich full screen documents with vertical scrolling):

This app

Demonstrations apps (Polyhedra example)

eBook apps

CDF content can supplement custom UI (smaller portions of screen, possibly fixed size):

Wolfram Calculator

Molecules example

Integrating CDFKit Into an App

Create a CDFSession:

CDFSession is your connection to CDFKit.  Create one (and only one) at app launch or the first time you need it.

Create a CDFDocument and CDFViewController

Each view must have a CDFDocument associated with it.  The CDFDocument can be empty, or created from a parsed Notebook[] expression, or read from a file on disk.

CDFViewController manages the CDF view.  Embed this view into your view hierarchy.

Perform evaluations and update CDF view

CDFExpr is used to represent Wolfram Language expressions in Objective-C.  CDFExpr can be parsed from InputForm, or constructed manually, or retrieved from kernel evaluations.

The CDFSession object contains a CDFEvaluator, which can be used to evaluated expressions.  All evaluations happen asynchronously.  They can either be queued (shift-enter) or preemptive (which could temporarily pause queued evaluations).  You supply a block (closure) to be called on a specified dispatch queue (thread) when the evaluation is complete.

The contents associated with a CDFViewController can be changed at any time.  The update will happen asynchronously and the view will be redrawn when the new contents are ready.  If you want line breaking (you probably do) you must first set the “format width” of the CDFViewController.

Link app with required libraries and frameworks

Copy SystemFiles to app bundle

Add a “Shell Script” build phase to your target in Xcode to copy the contents of the SystemFiles directory into your app bundle.

rsync -pvtrL "$CDFKIT/SystemFiles/" "$BUILT_PRODUCTS_DIR/$WRAPPER_NAME/SystemFiles/"

Activate Fonts

CDFKit includes fonts which must be activated in your app’s Info.plist.

Misc

Specify your app’s delegate class in the Info.plist (this is probably a temporary requirement).

Replace your call to UIMain() with CDFMain() (this is probably a temporary requirement).

Example: Molecules

Two simple Mathematica commands to generate the data file

Column[salts=Cases[ChemicalData["Salts"],x_/;Head[ChemicalData[x,"MoleculePlot"]]=!=Missing]]

Export[FileNameJoin[{NotebookDirectory[],"Salts.dat"}],Compress[{ChemicalData[#,"StandardName"],ChemicalData[#,"Name"],DeleteCases[ToBoxes[ChemicalData[#,"MoleculePlot"]],ImageSize->_]}&/@salts],"String"]

Read the data file at runtime

NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@”Salts” ofType:@”dat”]];
masterViewController.entries = [CDFExpr exprWithCompressedData:data];

TouchPosition

TouchPosition is the analog to MousePosition for touchscreen devices that don’t use mice.

MousePosition[]

Dynamic[TouchPosition[]]

GestureHandler

GestureHandler is the analog to EventHandler for dealing with touch gestures.

DynamicModule[{r=.5,c=1},GestureHandler[
Graphics[{Disk[{0,0},Dynamic[r]]},Background->Dynamic[{Red,Green,Blue}[[c]]],ImageSize->300,PlotRange->1],{
"Drag":>Function[r+=First[#]],
"Tap":>Function[c=Mod[c,3]+1]
}]]

TouchscreenControlPlacement

TouchscreenControlPlacement is an option to Manipulate[] allowing controls to be placed on any side of the screen only when displayed on a touchscreen device.

Manipulate[x,{x,0,1},ControlType->VerticalSlider, TouchscreenControlPlacement->Right]

TouchscreenAutoZoom

TouchscreenAutoZoom is an option to Manipulate[] that controls whether the content automatically zooms in to fill the screen when interacting with it.

Manipulate[Plot[Sin[a x],{x,0,2π}],{a,1,5},TouchscreenAutoZoom->True]

Manipulate[Plot[Sin[a x],{x,0,2π}],{a,1,5},TouchscreenAutoZoom->False]

Potential Issues

Incomplete features

EventHandler (only “MouseClicked” works)

TabView

Texture

Locator (only works inside Manipulate)

InputField

3D arrows (only works for Line)

2D arrows (don’t support custom setbacks)

network functionality

WolframAlpha function

JLink

DatabaseLink

Performance

constrained RAM

much slower CPU than desktops and laptops

Other limitations

kernel session cannot currently be restarted

WolframAlpha

WolframCloud

APIFunction in WolframCloud

Note the file creation date.  This is a pretty easy way to go.

The interesting stuff happens in performQuery().